#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>

#include "channel.h"
#include "cios.h"
#include "video.h"
#include "wiiuse/wpad.h"
#include "audio.h"


/* Constants */
#define ENTRIES_PER_PAGE	5

/* Variables */


channel *channel_list= NULL;
u32 channel_cnt=0;
u32  str_maxlen=0;
s32  start , selected;



int __Channel_Strcmp(const void *ptr1, const void *ptr2)
{
	const char *str1 = ((channel *)ptr1)->name;
	const char *str2 = ((channel *)ptr2)->name;

	/* Compare strings */
	return strcmp(str1, str2);
}

int __Channel_GetName(u64 tid, char *string)
{
	CIOS_Identify();
	static imet imet_data ATTRIBUTE_ALIGN(32);
	u16   *imet_name = NULL;

	tikview *views = NULL;

	u32 cnt, nb_views;
	s32 cfd = -1, ret;

	/* Get number of ticket views */
	ret = ES_GetNumTicketViews(tid, &nb_views);
	if (ret < 0)
		return ret;

	if (!nb_views)
		return -1;

	/* Allocate memory */
	views = (tikview *)memalign(32, sizeof(tikview) * nb_views);
	if (!views)
		return -1;

	/* Get ticket views */
	ret = ES_GetTicketViews(tid, views, nb_views);
	if (ret < 0)
		goto out;

	/* Open content 0 */
	cfd = ES_OpenTitleContent(tid, 0);
	if (cfd < 0) {
		ret = cfd;
		goto out;
	}

	/* Read content */
	ret = ES_ReadContent(cfd, (u8 *)&imet_data, sizeof(imet));
	if (ret < 0)
		goto out;

	/* Select channel name (in proper language) */
	ret = CONF_GetLanguage();

	switch (ret) {
	/* Japanese */
	case CONF_LANG_JAPANESE:	imet_name = imet_data.name_jp; break;
	/* German */
	case CONF_LANG_GERMAN:		imet_name = imet_data.name_de; break;
	/* French */
	case CONF_LANG_FRENCH:		imet_name = imet_data.name_fr; break;
	/* Spanish */
	case CONF_LANG_SPANISH:		imet_name = imet_data.name_es; break;
	/* Italian */
	case CONF_LANG_ITALIAN:		imet_name = imet_data.name_it; break;
	/* Dutch */
	case CONF_LANG_DUTCH:		imet_name = imet_data.name_nl; break;
	/* Default: English */
	default:			imet_name = imet_data.name_en;
	}

	/* No valid IMET name */
	if (!imet_name[0]) {
		/* Default language: English */
		imet_name = imet_data.name_en;

		/* No name, find one */
		if (!imet_name[0])
			imet_name = imet_data.name_de;
		if (!imet_name[0])
			imet_name = imet_data.name_fr;
		if (!imet_name[0])
			imet_name = imet_data.name_es;
		if (!imet_name[0])
			imet_name = imet_data.name_it;
		if (!imet_name[0])
			imet_name = imet_data.name_nl;
		if (!imet_name[0])
			imet_name = imet_data.name_jp;
	}

	/* Valid name found */
	if (imet_name[0]) {
		/* Copy channel name */
		for (cnt = 0; cnt < CHANNEL_NAME_LEN; cnt++)
			string[cnt] = imet_name[cnt];
	}

	/* Success */
	ret = 0;

out:
	/* Close content */
	if (cfd >= 0)
		ES_CloseContent(cfd);

	/* Free memory */
	if (views)
		free(views);

	return ret;
}

int Channel_Launch(void)
{
	tikview *views = NULL;
	u64        tid = channel_list[selected].tid;

	u32 nb_views;
	s32 ret;

	printf("\n");
	printf("[+] Launching title %016llX, please wait...", tid);
	fflush(stdout);

	/* Get number of ticket views */
	ret = ES_GetNumTicketViews(tid, &nb_views);
	if (ret < 0) {
		printf(" ERROR! Could not get number of ticket views! (ret = %d)\n", ret);
		return ret;
	}

	if (!nb_views) {
		printf(" ERROR! No ticket views! (ret = %d)\n", ret);
		return ret;
	}

	/* Allocate memory */
	views = (tikview *)memalign(32, sizeof(tikview) * nb_views);
	if (!views)
		return ret;

	/* Get ticket views */
	ret = ES_GetTicketViews(tid, views, nb_views);
	if (ret < 0) {
		printf(" ERROR! Could not get ticket views! (ret = %d)\n", ret);
		goto err;
	}

	/* Launch title */
	ret = ES_LaunchTitle(tid, &views[0]);
	if (ret < 0)
		printf(" ERROR! Could not launch title! (ret = %d)\n", ret);

err:
	/* Free memory */
	if (views)
		free(views);
	return ret;
}


void Channel_FreeList(void)
{
	/* Memory allocated */
	if (channel_list) {
		/* Free memory */
		free(channel_list);

		/* Set pointer to NULL */
		channel_list = NULL;
	}
}

s32 Channel_GetList(void)
{

	s32 IOS_Rev = IOS_GetVersion();
	if (!CIOS_IsLoaded())
	{	
		CIOS_Load();
		PAD_Init();
		WPAD_Init();
		InitVideo(); // Initialise video
	}
		
	start = 0;
	channel *channels = NULL;
	u64     *titles   = NULL;

	u32 cnt, idx, nb_titles;
	s32 ret;

	/* Free channel list */
	Channel_FreeList();

	/* Get number of titles */
	ret = ES_GetNumTitles(&nb_titles);
	if (ret < 0)
		return ret;

	/* No titles found */
	if (!nb_titles)
		return -1;

	/* Allocate memory */
	titles   =     (u64 *)memalign(32, sizeof(u64) * nb_titles);
	channels = (channel *)memalign(32, sizeof(channel) * nb_titles);

	if (!titles || !channels) {
		ret = -1;
		goto err;
	}

	/* Get title list */
	ret = ES_GetTitles(titles, nb_titles);
	if (ret < 0)
		goto err;

	/* Fill channel array */
	for (cnt = idx = 0; idx < nb_titles; idx++) {
		char name[CHANNEL_NAME_LEN] = "Unknown Channel";

		u32   id = (u32)(titles[idx] >> 32);
		u64  tid = titles[idx];

		/* Check if title is a channel */
		if (id != 0x10001 && id != 0x10002 && id != 0x10004)
			continue;

		/* Copy title ID */
		channels[cnt].tid = tid;

		/* Get channel name */
		ret = __Channel_GetName(tid, name);
		if (ret < 0 && CIOS_IsLoaded())
			continue;

		/* String max length */
		if (strlen(name) > str_maxlen)
			str_maxlen = strlen(name);

		/* Copy channel name */
		strcpy(channels[cnt].name, name);

		/* Increase counter */
		cnt++;
	}

	/* Sort channel list */
	qsort(channels, cnt, sizeof(channel),  __Channel_Strcmp);

	/* Set values */
	channel_list = channels;
	channel_cnt  = cnt;

	/* Success */
	ret = 0;

	goto out;

err:
	/* Free memory */
	if (channels)
		free(channels);

out:
	/* Free memory */
	if (titles)
		free(titles);
	IOS_ReloadIOS(IOS_Rev);

	return ret;
}
